package com.ak.game.util;

import com.ak.game.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;

/**
 * 通用工具类
 */
@Slf4j
@Component
public class CommonUtil implements ApplicationContextAware {

    private static ThreadPoolTaskExecutor threadPoolTaskExecutor;

    /**
     * 服务器时区
     */
    @Value("${serverTimeZone:Asia/Shanghai}")
    private String serverTimeZone;

    @Override
    public void setApplicationContext(ApplicationContext context) throws BeansException {
        threadPoolTaskExecutor = context.getBean(ThreadPoolTaskExecutor.class);
    }

    public static Date formatLong2Date(Object object) {
        return new Date(Long.parseLong(object.toString()));
    }

    public static Date formatString2Date(String strDate) throws ParseException {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        return formatter.parse(strDate);
    }

    /**
     * 动态sql注入
     *
     * @param id
     * @param selectByIdFunction
     * @param errorMessage
     * @param <T>
     * @return
     */
    public static <T> CompletableFuture<T> fetchAndVerifyEntity(String id, Function<String, T> selectByIdFunction, String errorMessage) {
        return CompletableFuture.supplyAsync(() -> {
            T entity = selectByIdFunction.apply(id);
            if (ObjectUtils.isEmpty(entity)) {
                log.error(errorMessage);
                throw new ServiceException(errorMessage);
            }
            return entity;
        }, threadPoolTaskExecutor);
    }

    /**
     * 游戏中的时区 跟 日本 时间的转换
     *
     * @param object  游戏时间 如: 2020-05-18 07:00:00
     * @param gameTimeZone 游戏时间的时区 如: GMT-4
     * @return 把游戏时间转换成日本时区
     */
    public Date parseDateToCountry(Object object, String gameTimeZone) {
        try {
            SimpleDateFormat formatter2Date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date time = new Date(Long.parseLong(object.toString()));
            String gameDateStr = formatter2Date.format(time);
            // String时间格式转换成为LocalDateTime格式
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            LocalDateTime parse = LocalDateTime.parse(gameDateStr, formatter);
            /** 按指定时区 解析 游戏时间 得到ZonedDateTime格式 */
            ZonedDateTime gameZoned = parse.atZone(ZoneId.of(gameTimeZone));
            ZonedDateTime targetTime = gameZoned.withZoneSameInstant(ZoneId.of(serverTimeZone));//转换成服务器的时区
            // ZonedDateTime格式转换成为String 再转换成为Date格式
            String targetTimeStr = targetTime.format(formatter);
            /**注:转成Date又是当前系统时间 因为Date.from原理就是new Date又是回到当前时间  但配合全局时区ApplicationConfig设置到字段中 即可设置对应的系统使用地的时区*/
            return formatter2Date.parse(targetTimeStr);
        } catch (Exception e) {
            log.error("GameDateParseUtil.parseDateToCountry()  游戏时间和系统使用地时间转换错误");
            throw new ServiceException("游戏时间和系统使用地时间转换错误");
        }
    }

    /**
     * "yyyy-MM-dd'T'HH:mm:ss.SSS"时间格式转换为"yyyy-MM-dd HH:mm:ss"
     *
     * @param time "yyyy-MM-dd'T'HH:mm:ss.SSS"
     * @return
     */
    public String formatDate(String time) {
        SimpleDateFormat formatter1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
        //他妈的 有些有毫秒 有些没得毫秒
        if (time.length() <= 19) {
            formatter1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
        }

        try {
            Date new_transaction_time = formatter1.parse(time);
            SimpleDateFormat formatter2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            return formatter2.format(new_transaction_time);
        } catch (ParseException e) {
            log.error("GameDateParseUtil.formatDate()  yyyy-MM-dd'T'HH:mm:ss.SSS时间格式转换为yyyy-MM-dd HH:mm:ss转换错误");
            throw new ServiceException("游戏时间和系统使用地时间转换错误");
        }
    }

    public static void main(String[] args) {

        System.out.println(System.currentTimeMillis());
        System.out.println(new Date(Long.parseLong("1716378000516")));
    }
}
